package cn.zhaoyuening.fanrpc.provider.core;

import cn.zhaoyuening.fanrpc.common.beans.RpcServiceAddress;
import cn.zhaoyuening.fanrpc.common.utils.FanRpcConstant;
import cn.zhaoyuening.fanrpc.common.utils.FanRpcUtils;
import cn.zhaoyuening.fanrpc.common.utils.JsonUtils;
import cn.zhaoyuening.fanrpc.provider.annotation.RpcService;
import org.apache.curator.framework.CuratorFramework;
import org.apache.zookeeper.CreateMode;
import org.apache.zookeeper.data.Stat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

@Component
public class RpcServer implements InitializingBean,ApplicationContextAware {

    @Value("${funrpc.server.address}")
    private String SERVER_ADDRESS;
    @Value("${funrpc.server.port}")
    private Integer SERVER_PORT;

    private Logger logger = LoggerFactory.getLogger(this.getClass());
    private ApplicationContext applicationContext;
    private Map<String, Object> rpcServiceMap = new HashMap();


    @Autowired
    private CuratorFramework zkClient;




    private void initRpcServiceMap(Map<String, Object> serviceMap) {
        for (Object service :
                serviceMap.values()) {
            Class zlass = service.getClass().getAnnotation(RpcService.class).value();
            String version = service.getClass().getAnnotation(RpcService.class).version();
            String serviceName = FanRpcUtils.classVersionToServiceName(zlass,version);
            logger.info("发现RpcService:"+serviceName);
            rpcServiceMap.put(serviceName, service);
        }
    }

    private void registerServiceToZk() throws Exception {
        logger.info("向zk注册服务");
        Object service = null;
        String rpcServiceAddressJson = JsonUtils.objectToJson(new RpcServiceAddress().setAddress(SERVER_ADDRESS).setPort(SERVER_PORT));
        for (String serviceName :
                rpcServiceMap.keySet()) {
            service = rpcServiceMap.get(serviceName);
            zkClient.create().withMode(CreateMode.EPHEMERAL).forPath(FanRpcConstant.ZK_NODE_ROOT+"/"+serviceName,rpcServiceAddressJson.getBytes());
        }
    }

    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public void afterPropertiesSet() throws Exception {
        logger.info("获取所有RpcService");
        Map<String, Object> serviceMap = applicationContext.getBeansWithAnnotation(RpcService.class);
        initRpcServiceMap(serviceMap);

        Stat stat = zkClient.checkExists().forPath(FanRpcConstant.ZK_NODE_ROOT);
        if (stat == null) {
            zkClient.create().forPath(FanRpcConstant.ZK_NODE_ROOT);
        }
        registerServiceToZk();
        RpcRequestListener rpcRequestListener = new RpcRequestListener(SERVER_PORT);
        rpcRequestListener.start(rpcServiceMap);
    }
}
